/**
  ******************************************************************************
  * @file    zb32l03x_hal_spi.c
  * @author  MCD Application Team
  * @Version V2.0.0
  * @Date    2022/08/23
  * @brief
  * @endverbatim
  */

#include "zb32l03x_hal.h"

/** @defgroup SPI SPI
  * @brief SPI HAL module driver
  * @{
  */
#ifdef HAL_SPI_I2S_MODULE_ENABLED
//=============================================================================
//                  Constant Definition
//=============================================================================
#define SPI_DEFAULT_TIMEOUT     100U
//=============================================================================
//                  Macro Definition
//=============================================================================
#define CORRECT_SPI_SLAVE     1

#if defined CORRECT_SPI_SLAVE && CORRECT_SPI_SLAVE

    #define CORRECT_SPI_ENABLE()                                 \
    do{                                                          \
        if(pHSpi->Init.Mode == SPI_MODE_MASTER)                  \
        {                                                        \
            __HAL_SPI_ENABLE(pHSpi);                             \
        }                                                        \
        else /* slave mode */                                    \
        {                                                        \
            SET_BIT(pHSpi->Instance->CR1, SPI_CR1_SSI);          \
            __HAL_SPI_ENABLE(pHSpi);                             \
            __NOP();__NOP();__NOP();__NOP();__NOP();             \
            __NOP();__NOP();__NOP();__NOP();__NOP();             \
            CLEAR_BIT(pHSpi->Instance->CR1, SPI_CR1_SSI);        \
        }                                                        \
    }while(0)
#else
    #define CORRECT_SPI_ENABLE()                                 \
    do{__HAL_SPI_ENABLE(pHSpi);}while(0)
#endif
//=============================================================================
//                  Structure Definition
//=============================================================================

//=============================================================================
//                  Global Data Definition
//=============================================================================

//=============================================================================
//                  Private Function Definition
//=============================================================================
static HAL_StatusTypeDef
_SPI_WaitFlagStateUntilTimeout(
    SPI_HandleTypeDef   *pHSpi,
    uint32_t            Flag,
    FlagStatus          State,
    uint32_t            Timeout,
    uint32_t            Tickstart)
{
    __IO uint32_t  count = 0;
    uint32_t tmp_timeout = 0;
    uint32_t tmp_tickstart = 0;

    tmp_timeout   = Timeout - (HAL_GetTick() - Tickstart);
    tmp_tickstart = HAL_GetTick();
    count = tmp_timeout * ((SystemCoreClock * 32U) >> 20U);

    while ((__HAL_SPI_GET_FLAG(pHSpi, Flag) ? SET : RESET) != State)
    {
        if (Timeout == HAL_MAX_DELAY)
            continue;

        if (((HAL_GetTick() - tmp_tickstart) >= tmp_timeout) || (tmp_timeout == 0U))
        {
            /* Disable TXE, RXNE and ERR interrupts for the interrupt process */
            CLEAR_BIT(pHSpi->Instance->CR2, (SPI_IT_TXE | SPI_IT_RXNE | SPI_IT_ERR));

            if ((pHSpi->Init.Mode == SPI_MODE_MASTER) &&
                ((pHSpi->Init.Direction == SPI_DIRECTION_1LINE) || (pHSpi->Init.Direction == SPI_DIRECTION_2LINES_RXONLY)))
            {
                /* Disable SPI */
                CLEAR_BIT(pHSpi->Instance->CR1, SPI_CR1_SPE);
            }

            if (pHSpi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
            {
              SPI_RESET_CRC(pHSpi);
            }

            pHSpi->State = HAL_SPI_STATE_READY;

            return HAL_TIMEOUT;
        }
        /* If Systick is disabled or not incremented, deactivate timeout to go in disable loop procedure */
        if(count == 0U)
        {
          tmp_timeout = 0U;
        }
        count--;
    }
    return HAL_OK;
}

static void
_SPI_Rx_DisableSpi(struct __SPI_HandleTypeDef *pHSpi)
{
#if (USE_SPI_CRC == 0U)
    if(pHSpi->RxXferCount == 1)
    {
        if ((pHSpi->Init.Mode == SPI_MODE_MASTER) &&
        ((pHSpi->Init.Direction == SPI_DIRECTION_1LINE) || (pHSpi->Init.Direction == SPI_DIRECTION_2LINES_RXONLY)))
        {
            /* Disable SPI */
            CLEAR_BIT(pHSpi->Instance->CR1, SPI_CR1_SPE);
        }
    }
#endif
}

static HAL_StatusTypeDef
_SPI_EndRxTransaction(
    SPI_HandleTypeDef   *pHSpi,
    uint32_t            Timeout,
    uint32_t            Tickstart)
{
    HAL_StatusTypeDef rval = HAL_OK;

//    if ((pHSpi->Init.Mode == SPI_MODE_MASTER) &&
//        ((pHSpi->Init.Direction == SPI_DIRECTION_1LINE) || (pHSpi->Init.Direction == SPI_DIRECTION_2LINES_RXONLY)))
//    {
//        /* Disable SPI */
//        CLEAR_BIT(pHSpi->Instance->CR1, SPI_CR1_SPE);
//    }

    if ((pHSpi->Init.Mode == SPI_MODE_MASTER) && (pHSpi->Init.Direction == SPI_DIRECTION_2LINES_RXONLY))
    {
        rval = _SPI_WaitFlagStateUntilTimeout(pHSpi, SPI_FLAG_RXNE, RESET, Timeout, Tickstart);
        if (rval == HAL_TIMEOUT)
        {
        SET_BIT(pHSpi->ErrorCode, HAL_SPI_ERROR_FLAG);
        __HAL_UNLOCK(pHSpi);
        return HAL_TIMEOUT;
        }
    }
    else
    {
        rval = _SPI_WaitFlagStateUntilTimeout(pHSpi, SPI_FLAG_BSY, RESET, Timeout, Tickstart);
        if (rval == HAL_TIMEOUT)
        {
          SET_BIT(pHSpi->ErrorCode, HAL_SPI_ERROR_FLAG);
          __HAL_UNLOCK(pHSpi);
          return HAL_TIMEOUT;
        }
    }
    return HAL_OK;
}


static HAL_StatusTypeDef
_SPI_EndRxTxTransaction(
    SPI_HandleTypeDef   *pHSpi,
    uint32_t            Timeout,
    uint32_t            Tickstart)
{
    HAL_StatusTypeDef rval = HAL_OK;

    rval = _SPI_WaitFlagStateUntilTimeout(pHSpi, SPI_FLAG_BSY, RESET, Timeout, Tickstart);
    if (rval == HAL_TIMEOUT)
    {
        SET_BIT(pHSpi->ErrorCode, HAL_SPI_ERROR_FLAG);
        __HAL_UNLOCK(pHSpi);
        return HAL_TIMEOUT;
    }
    return HAL_OK;
}

static void
_SPI_AbortRx_ISR(SPI_HandleTypeDef *pHSpi)
{
    __IO uint32_t tmpreg = 0U;
    __IO uint32_t count = SPI_DEFAULT_TIMEOUT * (SystemCoreClock / 24U / 1000U);

    /* Wait until TXE flag is set */
    do
    {
        if (count == 0U)
        {
          SET_BIT(pHSpi->ErrorCode, HAL_SPI_ERROR_ABORT);
          break;
        }
        count--;
    } while ((pHSpi->Instance->SR & SPI_FLAG_TXE) == RESET);

    CLEAR_BIT(pHSpi->Instance->CR1, SPI_CR1_SPE);

    CLEAR_BIT(pHSpi->Instance->CR2, (SPI_CR2_TXEIE | SPI_CR2_RXNEIE | SPI_CR2_ERRIE));

    tmpreg = READ_REG(pHSpi->Instance->DR);

    UNUSED(tmpreg);

    pHSpi->State = HAL_SPI_STATE_ABORT;
}


static void
_SPI_AbortTx_ISR(SPI_HandleTypeDef *pHSpi)
{
    CLEAR_BIT(pHSpi->Instance->CR2, (SPI_CR2_TXEIE));

    CLEAR_BIT(pHSpi->Instance->CR1, SPI_CR1_SPE);

    pHSpi->State = HAL_SPI_STATE_ABORT;
}

static void
_SPI_CloseRxTx_ISR(SPI_HandleTypeDef *pHSpi)
{
    uint32_t tickstart = 0;
    __IO uint32_t count = SPI_DEFAULT_TIMEOUT * (SystemCoreClock / 24U / 1000U);

    tickstart = HAL_GetTick();

    /* Disable ERR interrupt */
    CLEAR_BIT( pHSpi->Instance->CR2, SPI_IT_ERR);

    /* Wait until TXE flag is set */
    do
    {
        if (count == 0U)
        {
            SET_BIT(pHSpi->ErrorCode, HAL_SPI_ERROR_FLAG);
            break;
        }
        count--;
    } while ((pHSpi->Instance->SR & SPI_FLAG_TXE) == RESET);

    if (_SPI_EndRxTxTransaction(pHSpi, SPI_DEFAULT_TIMEOUT, tickstart) != HAL_OK)
    {
        SET_BIT(pHSpi->ErrorCode, HAL_SPI_ERROR_FLAG);
    }

    if (pHSpi->Init.Direction == SPI_DIRECTION_2LINES)
    {
        __HAL_SPI_CLEAR_OVRFLAG(pHSpi);
    }

#if (USE_SPI_CRC != 0U)
    if (__HAL_SPI_GET_FLAG(pHSpi, SPI_FLAG_CRCERR) != RESET)
    {
        pHSpi->State = HAL_SPI_STATE_READY;
        SET_BIT(pHSpi->ErrorCode, HAL_SPI_ERROR_CRC);

        SPI_RESET_CRC(pHSpi);
        HAL_SPI_ErrorCallback(pHSpi);
    }
    else
    {
#endif /* USE_SPI_CRC */
        if (pHSpi->ErrorCode == HAL_SPI_ERROR_NONE)
        {
            if (pHSpi->State == HAL_SPI_STATE_BUSY_RX)
            {
                pHSpi->State = HAL_SPI_STATE_READY;
                HAL_SPI_RxCpltCallback(pHSpi);
            }
            else
            {
                pHSpi->State = HAL_SPI_STATE_READY;
                HAL_SPI_TxRxCpltCallback(pHSpi);
            }
        }
        else
        {
            pHSpi->State = HAL_SPI_STATE_READY;
            HAL_SPI_ErrorCallback(pHSpi);
        }
#if (USE_SPI_CRC != 0U)
    }
#endif /* USE_SPI_CRC */
}
static void
_SPI_CloseRx_ISR(SPI_HandleTypeDef *pHSpi)
{
    /* Disable RXNE and ERR interrupt */
    CLEAR_BIT(pHSpi->Instance->CR2, (SPI_IT_RXNE | SPI_IT_ERR));

    if (_SPI_EndRxTransaction(pHSpi, SPI_DEFAULT_TIMEOUT, HAL_GetTick()) != HAL_OK)
    {
        SET_BIT(pHSpi->ErrorCode, HAL_SPI_ERROR_FLAG);
    }

    if (pHSpi->Init.Direction == SPI_DIRECTION_2LINES)
    {
        __HAL_SPI_CLEAR_OVRFLAG(pHSpi);
    }
    pHSpi->State = HAL_SPI_STATE_READY;

#if (USE_SPI_CRC != 0U)

    if (__HAL_SPI_GET_FLAG(pHSpi, SPI_FLAG_CRCERR) != RESET)
    {
        SET_BIT(pHSpi->ErrorCode, HAL_SPI_ERROR_CRC);

        SPI_RESET_CRC(pHSpi);

        HAL_SPI_ErrorCallback(pHSpi);
    }
    else
    {
#endif /* USE_SPI_CRC */
        if (pHSpi->ErrorCode == HAL_SPI_ERROR_NONE)
        {
            HAL_SPI_RxCpltCallback(pHSpi);
        }
        else
        {
            HAL_SPI_ErrorCallback(pHSpi);
        }
#if (USE_SPI_CRC != 0U)
    }
#endif /* USE_SPI_CRC */
}


#if (USE_SPI_CRC != 0U)

static void
_SPI_2linesRxISR_8BITCRC(struct __SPI_HandleTypeDef *pHSpi)
{
    __IO uint8_t  * ptmpreg8;
    __IO uint8_t  tmpreg8 = 0;

    ptmpreg8 = (__IO uint8_t *)&pHSpi->Instance->DR;

    tmpreg8 = *ptmpreg8;

    UNUSED(tmpreg8);

    /* Disable RXNE and ERR interrupt */
    CLEAR_BIT(pHSpi->Instance->CR2, (SPI_IT_RXNE | SPI_IT_ERR));

    if (pHSpi->TxXferCount == 0U)
    {
        _SPI_CloseRxTx_ISR(pHSpi);
    }
}

static void
_SPI_2linesRxISR_16BITCRC(struct __SPI_HandleTypeDef *pHSpi)
{
    __IO uint32_t tmpreg = 0U;

    tmpreg = READ_REG(pHSpi->Instance->DR);

    UNUSED(tmpreg);

    /* Disable RXNE interrupt */
    CLEAR_BIT(pHSpi->Instance->CR2, SPI_IT_RXNE);

    _SPI_CloseRxTx_ISR(pHSpi);
}

static void
_SPI_RxISR_16BITCRC(struct __SPI_HandleTypeDef *pHSpi)
{
    __IO uint32_t tmpreg = 0U;

    tmpreg = READ_REG(pHSpi->Instance->DR);

    UNUSED(tmpreg);

    /* Disable RXNE and ERR interrupt */
    CLEAR_BIT(pHSpi->Instance->CR2, (SPI_IT_RXNE | SPI_IT_ERR));

    _SPI_CloseRx_ISR(pHSpi);
}

static void
_SPI_RxISR_8BITCRC(struct __SPI_HandleTypeDef *pHSpi)
{
    __IO uint8_t  * ptmpreg8;
    __IO uint8_t  tmpreg8 = 0;

    ptmpreg8 = (__IO uint8_t *)&pHSpi->Instance->DR;

    tmpreg8 = *ptmpreg8;

    UNUSED(tmpreg8);

    _SPI_CloseRx_ISR(pHSpi);
}

#endif /* USE_SPI_CRC */

static void
_SPI_CloseTx_ISR(SPI_HandleTypeDef *pHSpi)
{
    uint32_t tickstart = 0;
    __IO uint32_t count = SPI_DEFAULT_TIMEOUT * (SystemCoreClock / 24U / 1000U);

    tickstart = HAL_GetTick();

    /* Wait until TXE flag is set */
    do
    {
        if (count == 0U)
        {
            SET_BIT(pHSpi->ErrorCode, HAL_SPI_ERROR_FLAG);
            break;
        }
        count--;
    } while ((pHSpi->Instance->SR & SPI_FLAG_TXE) == RESET);

    /* Disable TXE and ERR interrupt */
    CLEAR_BIT(pHSpi->Instance->CR2, (SPI_IT_TXE | SPI_IT_ERR));

    if (_SPI_EndRxTxTransaction(pHSpi, SPI_DEFAULT_TIMEOUT, tickstart) != HAL_OK)
    {
        SET_BIT(pHSpi->ErrorCode, HAL_SPI_ERROR_FLAG);
    }

    if (pHSpi->Init.Direction == SPI_DIRECTION_2LINES)
    {
        __HAL_SPI_CLEAR_OVRFLAG(pHSpi);
    }

    pHSpi->State = HAL_SPI_STATE_READY;

    if (pHSpi->ErrorCode != HAL_SPI_ERROR_NONE)
    {
        HAL_SPI_ErrorCallback(pHSpi);
    }
    else
    {
        HAL_SPI_TxCpltCallback(pHSpi);
    }
}


static void
_SPI_2linesRxISR_8BIT(struct __SPI_HandleTypeDef *pHSpi)
{
    /* Receive data in 8bit mode */
    *pHSpi->pRxBuffPtr = *((__IO uint8_t *)&pHSpi->Instance->DR);
    pHSpi->pRxBuffPtr++;
    pHSpi->RxXferCount--;

    if (pHSpi->RxXferCount == 0U)
    {
#if (USE_SPI_CRC != 0U)
        if (pHSpi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
        {
            pHSpi->RxISR =  _SPI_2linesRxISR_8BITCRC;
            return;
        }
#endif /* USE_SPI_CRC */

        /* Disable RXNE  and ERR interrupt */
        CLEAR_BIT(pHSpi->Instance->CR2, (SPI_IT_RXNE | SPI_IT_ERR));

        if (pHSpi->TxXferCount == 0U)
        {
            _SPI_CloseRxTx_ISR(pHSpi);
        }
    }
}


static void
_SPI_2linesTxISR_8BIT(struct __SPI_HandleTypeDef *pHSpi)
{
    /* Transmit data in 8bit mode */
#if (USE_SPI_CRC != 0U)
    if (pHSpi->TxXferCount != 0U)
    {
#endif /* USE_SPI_CRC */
        *(__IO uint8_t *)&pHSpi->Instance->DR = (*pHSpi->pTxBuffPtr);
        pHSpi->pTxBuffPtr++;
        pHSpi->TxXferCount--;
#if (USE_SPI_CRC != 0U)
    }
    else
    {
        if (pHSpi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
        {
            SET_BIT(pHSpi->Instance->CR1, SPI_CR1_CRCNEXT);
            /* Disable TXE interrupt */
            CLEAR_BIT(pHSpi->Instance->CR2, SPI_IT_TXE);
            return;
        }
#else
    if (pHSpi->TxXferCount == 0U)
    {
#endif /* USE_SPI_CRC */

        /* Disable TXE interrupt */
        CLEAR_BIT(pHSpi->Instance->CR2, SPI_IT_TXE);

        if (pHSpi->RxXferCount == 0U)
        {
            _SPI_CloseRxTx_ISR(pHSpi);
        }
    }
}

static void
_SPI_2linesRxISR_16BIT(struct __SPI_HandleTypeDef *pHSpi)
{
    /* Receive data in 16 Bit mode */
    *((uint16_t *)pHSpi->pRxBuffPtr) = (uint16_t)(pHSpi->Instance->DR);
    pHSpi->pRxBuffPtr += sizeof(uint16_t);
    pHSpi->RxXferCount--;

    if (pHSpi->RxXferCount == 0U)
    {
#if (USE_SPI_CRC != 0U)
        if (pHSpi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
        {
            pHSpi->RxISR =  _SPI_2linesRxISR_16BITCRC;
            return;
        }
#endif /* USE_SPI_CRC */

        /* Disable RXNE interrupt */
        CLEAR_BIT(pHSpi->Instance->CR2, SPI_IT_RXNE);

        if (pHSpi->TxXferCount == 0U)
        {
            _SPI_CloseRxTx_ISR(pHSpi);
        }
    }
}


static void
_SPI_2linesTxISR_16BIT(struct __SPI_HandleTypeDef *pHSpi)
{
    /* Transmit data in 16 Bit mode */
#if (USE_SPI_CRC != 0U)
    if (pHSpi->TxXferCount != 0U)
    {
#endif /* USE_SPI_CRC */
        /* Transmit data in 16 Bit mode */
        pHSpi->Instance->DR = *((uint16_t *)pHSpi->pTxBuffPtr);
        pHSpi->pTxBuffPtr += sizeof(uint16_t);
        pHSpi->TxXferCount--;

#if (USE_SPI_CRC != 0U)
    }
    else
    {
        if (pHSpi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
        {
            SET_BIT(pHSpi->Instance->CR1, SPI_CR1_CRCNEXT);
            /* Disable TXE interrupt */
            CLEAR_BIT(pHSpi->Instance->CR2, SPI_IT_TXE);
            return;
        }
#else
    if (pHSpi->TxXferCount == 0U)
    {
#endif /* USE_SPI_CRC */
        /* Disable TXE interrupt */
        CLEAR_BIT(pHSpi->Instance->CR2, SPI_IT_TXE);

        if (pHSpi->RxXferCount == 0U)
        {
            _SPI_CloseRxTx_ISR(pHSpi);
        }
    }
}


static void
_SPI_RxISR_8BIT(struct __SPI_HandleTypeDef *pHSpi)
{
    /* Receive data in 8 Bit mode */
    *pHSpi->pRxBuffPtr = (*(__IO uint8_t *)&pHSpi->Instance->DR);
    pHSpi->pRxBuffPtr++;
    pHSpi->RxXferCount--;

    _SPI_Rx_DisableSpi(pHSpi);

#if (USE_SPI_CRC != 0U)

    if ((pHSpi->RxXferCount == 1U) && (pHSpi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE))
    {
        SET_BIT(pHSpi->Instance->CR1, SPI_CR1_CRCNEXT);

        if ((pHSpi->Init.Mode == SPI_MODE_MASTER) &&
        ((pHSpi->Init.Direction == SPI_DIRECTION_1LINE) || (pHSpi->Init.Direction == SPI_DIRECTION_2LINES_RXONLY)))
        {
            /* Disable SPI */
            CLEAR_BIT(pHSpi->Instance->CR1, SPI_CR1_SPE);
        }
    }
    if (READ_BIT(pHSpi->Instance->CR1, SPI_CR1_CRCNEXT))
    {
        CLEAR_BIT(pHSpi->Instance->CR1, SPI_CR1_CRCNEXT);
    }

#endif /* USE_SPI_CRC */

    if (pHSpi->RxXferCount == 0U)
    {
#if (USE_SPI_CRC != 0U)
        if (pHSpi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
        {
            pHSpi->RxISR =  _SPI_RxISR_8BITCRC;
            return;
        }
#endif /* USE_SPI_CRC */
        _SPI_CloseRx_ISR(pHSpi);
    }
}


static void
_SPI_RxISR_16BIT(struct __SPI_HandleTypeDef *pHSpi)
{
    /* Receive data in 16 Bit mode */
    *((uint16_t *)pHSpi->pRxBuffPtr) = (uint16_t)(pHSpi->Instance->DR);
    pHSpi->pRxBuffPtr += sizeof(uint16_t);
    pHSpi->RxXferCount--;

    _SPI_Rx_DisableSpi(pHSpi);

#if (USE_SPI_CRC != 0U)
    if ((pHSpi->RxXferCount == 1U) && (pHSpi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE))
    {
        SET_BIT(pHSpi->Instance->CR1, SPI_CR1_CRCNEXT);
        if ((pHSpi->Init.Mode == SPI_MODE_MASTER) &&
        ((pHSpi->Init.Direction == SPI_DIRECTION_1LINE) || (pHSpi->Init.Direction == SPI_DIRECTION_2LINES_RXONLY)))
        {
            /* Disable SPI */
            CLEAR_BIT(pHSpi->Instance->CR1, SPI_CR1_SPE);
        }
    }
    if (READ_BIT(pHSpi->Instance->CR1, SPI_CR1_CRCNEXT))
    {
        CLEAR_BIT(pHSpi->Instance->CR1, SPI_CR1_CRCNEXT);
    }

#endif /* USE_SPI_CRC */

    if (pHSpi->RxXferCount == 0U)
    {
#if (USE_SPI_CRC != 0U)
        if (pHSpi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
        {
            pHSpi->RxISR = _SPI_RxISR_16BITCRC;
            return;
        }
#endif /* USE_SPI_CRC */
        _SPI_CloseRx_ISR(pHSpi);
    }
}

static void
_SPI_TxISR_8BIT(struct __SPI_HandleTypeDef *pHSpi)
{
    /* Transmit data in 8 Bit mode */
    *(__IO uint8_t *)&pHSpi->Instance->DR = (*pHSpi->pTxBuffPtr);
    pHSpi->pTxBuffPtr++;
    pHSpi->TxXferCount--;

    if (pHSpi->TxXferCount == 0U)
    {
#if (USE_SPI_CRC != 0U)
        if (pHSpi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
        {
          SET_BIT(pHSpi->Instance->CR1, SPI_CR1_CRCNEXT);
        }
#endif /* USE_SPI_CRC */
        _SPI_CloseTx_ISR(pHSpi);
    }
}

static void
_SPI_TxISR_16BIT(struct __SPI_HandleTypeDef *pHSpi)
{
    /* Transmit data in 16 Bit mode */
    pHSpi->Instance->DR = *((uint16_t *)pHSpi->pTxBuffPtr);
    pHSpi->pTxBuffPtr += sizeof(uint16_t);
    pHSpi->TxXferCount--;

    if (pHSpi->TxXferCount == 0U)
    {
#if (USE_SPI_CRC != 0U)
        if (pHSpi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
        {
            SET_BIT(pHSpi->Instance->CR1, SPI_CR1_CRCNEXT);
        }
#endif /* USE_SPI_CRC */
        _SPI_CloseTx_ISR(pHSpi);
    }
}

static HAL_StatusTypeDef
_SPI_DMA_Config(
    HAL_DMA_Handle_TypeDef          *hdma,
    HAL_DMA_Channel_TypeDef         channel_id,
    HAL_DMA_Descriptor_Cfg_TypeDef  *pDescriptorCfg)
{
    HAL_DMA_Xfer_Cfg_TypeDef    transfer_cfg;
    HAL_StatusTypeDef           status = HAL_OK;

    status = HAL_DMA_Set_Descriptor(hdma, channel_id, pDescriptorCfg, 0);
    if( status != HAL_OK )
        return HAL_ERROR;

    // Start DMA
    transfer_cfg.is_immediate = 0;
    transfer_cfg.mode         = HAL_DMA_MODE_BASIC;
    transfer_cfg.type         = DMA_DESCRIPTOR_TYPE_PRIMARY;
    transfer_cfg.timeout      = -1;
    status = HAL_DMA_Channel_Sart(hdma, channel_id, &transfer_cfg);
    if( status != HAL_OK )  return HAL_ERROR;

    return HAL_OK;
}

//=============================================================================
//                  Public Function Definition
//=============================================================================
/**
  * @brief  Initialize the SPI according to the specified parameters
  *         in the SPI_InitTypeDef and initialize the associated handle.
  * @param  pHSpi : SPI handle
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_SPI_Init(SPI_HandleTypeDef *pHSpi)
{
    assert_param(IS_SPI_ALL_INSTANCE(pHSpi->Instance));
    assert_param(IS_SPI_MODE(pHSpi->Init.Mode));
    assert_param(IS_SPI_DIRECTION(pHSpi->Init.Direction));
    assert_param(IS_SPI_DATASIZE(pHSpi->Init.DataSize));
    assert_param(IS_SPI_NSS(pHSpi->Init.NSS));
    assert_param(IS_SPI_BAUDRATE_PRESCALER(pHSpi->Init.BaudRatePrescaler));
    assert_param(IS_SPI_FIRST_BIT(pHSpi->Init.FirstBit));
    assert_param(IS_SPI_CPOL(pHSpi->Init.CLKPolarity));
    assert_param(IS_SPI_CPHA(pHSpi->Init.CLKPhase));

    if (!pHSpi)
        return HAL_ERROR;

    if (pHSpi->Init.Mode == SPI_MODE_MASTER)
    {
        assert_param(IS_SPI_BAUDRATE_PRESCALER(pHSpi->Init.BaudRatePrescaler));
    }
    else
    {
        pHSpi->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
    }

#if (USE_SPI_CRC != 0U)
    assert_param(IS_SPI_CRC_CALCULATION(pHSpi->Init.CRCCalculation));
    if (pHSpi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
    {
        assert_param(IS_SPI_CRC_POLYNOMIAL(pHSpi->Init.CRCPolynomial));
    }
#else
    pHSpi->Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
#endif /* USE_SPI_CRC */

    if (pHSpi->State == HAL_SPI_STATE_RESET)
    {
        pHSpi->Lock = HAL_UNLOCKED;
        HAL_SPI_MspInit(pHSpi);
    }

    pHSpi->State = HAL_SPI_STATE_BUSY;

    /* Disable the selected SPI */
    CLEAR_BIT(pHSpi->Instance->CR1, SPI_CR1_SPE);

    /* SPI CR1 & CR2 Configuration */
    WRITE_REG(pHSpi->Instance->CR1, ((pHSpi->Init.Mode & (SPI_CR1_MSTR | SPI_CR1_SSI)) |
                                    (pHSpi->Init.Direction & (SPI_CR1_RXONLY | SPI_CR1_BIDIMODE)) |
                                    (pHSpi->Init.DataSize & SPI_CR1_DFF) |
                                    (pHSpi->Init.CLKPolarity & SPI_CR1_CPOL) |
                                    (pHSpi->Init.CLKPhase & SPI_CR1_CPHA) |
                                    (pHSpi->Init.NSS & SPI_CR1_SSM) |
                                    (pHSpi->Init.BaudRatePrescaler & SPI_CR1_BR_Msk) |
                                    (pHSpi->Init.FirstBit  & SPI_CR1_LSBFIRST) |
                                    (pHSpi->Init.CRCCalculation & SPI_CR1_CRCEN)));

    WRITE_REG(pHSpi->Instance->CR2, ((pHSpi->Init.NSS >> 16U) & SPI_CR2_SSOE));

#if (USE_SPI_CRC != 0U)
    /* Configure : CRC Polynomial */
    if (pHSpi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
    {
        WRITE_REG(pHSpi->Instance->CRCPR, (pHSpi->Init.CRCPolynomial & SPI_CRCPR_CRCPOLY_Msk));
    }
#endif /* USE_SPI_CRC */

    /* Activate the SPI mode (Make sure that I2SMOD bit in I2SCFGR register is reset) */
    CLEAR_BIT(pHSpi->Instance->I2SCFGR, SPI_I2SCFGR_I2SMOD);

    pHSpi->ErrorCode = HAL_SPI_ERROR_NONE;
    pHSpi->State     = HAL_SPI_STATE_READY;

    return HAL_OK;
}

/**
  * @brief  De-Initialize the SPI peripheral.
  * @param  [in] pHSpi       Pointer to a SPI_HandleTypeDef structure that contains
  *                         the configuration information for SPI module.
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_SPI_DeInit(SPI_HandleTypeDef *pHSpi)
{
    assert_param(IS_SPI_ALL_INSTANCE(pHSpi->Instance));

    if (!pHSpi)
        return HAL_ERROR;

    pHSpi->State = HAL_SPI_STATE_BUSY;

    /* Disable the SPI */
    CLEAR_BIT(pHSpi->Instance->CR1, SPI_CR1_SPE);

    HAL_SPI_MspDeInit(pHSpi);

    pHSpi->ErrorCode = HAL_SPI_ERROR_NONE;
    pHSpi->State = HAL_SPI_STATE_RESET;

    __HAL_UNLOCK(pHSpi);

    return HAL_OK;
}


/**
  * @brief  HAL_SPI_Transmit
  *             Transmit an amount of data in blocking mode.
  * @param  [in] pHSpi       Pointer to a SPI_HandleTypeDef structure that contains
  *                         the configuration information for SPI module.
  * @param  [in] pData      Pointer to data buffer
  * @param  [in] Size       Amount of data to be sent
  * @param  [in] Timeout    Timeout duration
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_SPI_Transmit(SPI_HandleTypeDef *pHSpi, uint8_t *pData, uint16_t Size, uint32_t Timeout)
{
    uint32_t tickstart = 0;
    HAL_StatusTypeDef errorcode = HAL_OK;
    uint16_t initial_TxXferCount = 0;

    assert_param(IS_SPI_DIRECTION_2LINES_OR_1LINE(pHSpi->Init.Direction));

    if ((!pData) || (!Size))
        return HAL_ERROR;

    tickstart = HAL_GetTick();

    if (pHSpi->State != HAL_SPI_STATE_READY)
        return HAL_BUSY;

    __HAL_LOCK(pHSpi);

    initial_TxXferCount = Size;

    pHSpi->State       = HAL_SPI_STATE_BUSY_TX;
    pHSpi->ErrorCode   = HAL_SPI_ERROR_NONE;
    pHSpi->pTxBuffPtr  = (uint8_t *)pData;
    pHSpi->TxXferSize  = Size;
    pHSpi->TxXferCount = Size;

    pHSpi->pRxBuffPtr  = (uint8_t *)NULL;
    pHSpi->RxXferSize  = 0U;
    pHSpi->RxXferCount = 0U;
    pHSpi->TxISR       = NULL;
    pHSpi->RxISR       = NULL;

    if (pHSpi->Init.Direction == SPI_DIRECTION_1LINE)
    {
        /* Disable SPI Peripheral before set 1Line direction (BIDIOE bit) */
        CLEAR_BIT(pHSpi->Instance->CR1, SPI_CR1_SPE);
        SPI_1LINE_TX(pHSpi);
    }

#if (USE_SPI_CRC != 0U)
    if (pHSpi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
    {
        SPI_RESET_CRC(pHSpi);
    }
#endif /* USE_SPI_CRC */

    /* Check if the SPI is already enabled. If not, enable SPI */
    if ((pHSpi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
    {
        CORRECT_SPI_ENABLE();
    }

    /* Transmit data in 16 Bit mode */
    if (pHSpi->Init.DataSize == SPI_DATASIZE_16BIT)
    {
        if ((pHSpi->Init.Mode == SPI_MODE_SLAVE) || (initial_TxXferCount == 0x01U))
        {
            pHSpi->Instance->DR = *((uint16_t *)pHSpi->pTxBuffPtr);
            pHSpi->pTxBuffPtr += sizeof(uint16_t);
            pHSpi->TxXferCount--;
        }
        while (pHSpi->TxXferCount > 0U)
        {
            /* Wait until TXE flag is set to send data */
            if (__HAL_SPI_GET_FLAG(pHSpi, SPI_FLAG_TXE))
            {
                pHSpi->Instance->DR = *((uint16_t *)pHSpi->pTxBuffPtr);
                pHSpi->pTxBuffPtr += sizeof(uint16_t);
                pHSpi->TxXferCount--;
            }
            else
            {
                /* Timeout management */
                if ((((HAL_GetTick() - tickstart) >=  Timeout) && (Timeout != HAL_MAX_DELAY)) || (Timeout == 0U))
                {
                    errorcode = HAL_TIMEOUT;
                    goto error;
                }
            }
        }
    }
    /* Transmit data in 8 Bit mode */
    else
    {
        if ((pHSpi->Init.Mode == SPI_MODE_SLAVE) || (initial_TxXferCount == 0x01U))
        {
            *((__IO uint8_t *)&pHSpi->Instance->DR) = (*pHSpi->pTxBuffPtr);
            pHSpi->pTxBuffPtr += sizeof(uint8_t);
            pHSpi->TxXferCount--;
        }
        while (pHSpi->TxXferCount > 0U)
        {
            /* Wait until TXE flag is set to send data */
            if (__HAL_SPI_GET_FLAG(pHSpi, SPI_FLAG_TXE))
            {
                *((__IO uint8_t *)&pHSpi->Instance->DR) = (*pHSpi->pTxBuffPtr);
                pHSpi->pTxBuffPtr += sizeof(uint8_t);
                pHSpi->TxXferCount--;
            }
            else
            {
                /* Timeout management */
                if ((((HAL_GetTick() - tickstart) >=  Timeout) && (Timeout != HAL_MAX_DELAY)) || (Timeout == 0U))
                {
                    errorcode = HAL_TIMEOUT;
                    goto error;
                }
            }
        }
    }
#if (USE_SPI_CRC != 0U)
    /* Enable CRC Transmission */
    if (pHSpi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
    {
        SET_BIT(pHSpi->Instance->CR1, SPI_CR1_CRCNEXT);
    }
#endif /* USE_SPI_CRC */

    /* Check the end of the transaction */
    if (_SPI_EndRxTxTransaction(pHSpi, Timeout, tickstart) != HAL_OK)
    {
        pHSpi->ErrorCode = HAL_SPI_ERROR_FLAG;
    }

    /* Clear overrun flag in 2 Lines communication mode because received is not read */
    if (pHSpi->Init.Direction == SPI_DIRECTION_2LINES)
    {
        __HAL_SPI_CLEAR_OVRFLAG(pHSpi);
    }

    if (pHSpi->ErrorCode != HAL_SPI_ERROR_NONE)
    {
        errorcode = HAL_ERROR;
    }

error:
    pHSpi->State = HAL_SPI_STATE_READY;
    __HAL_UNLOCK(pHSpi);
    return errorcode;
}

/**
  * @brief  HAL_SPI_Receive
  *             Receive an amount of data in blocking mode.
  * @param  [in] pHSpi       Pointer to a SPI_HandleTypeDef structure that contains
  *                         the configuration information for SPI module.
  * @param  [in] pData      Pointer to data buffer
  * @param  [in] Size       Amount of data to be received
  * @param  [in] Timeout    Timeout duration
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_SPI_Receive(SPI_HandleTypeDef *pHSpi, uint8_t *pData, uint16_t Size, uint32_t Timeout)
{
#if (USE_SPI_CRC != 0U)
    __IO uint32_t tmpreg = 0U;
#endif /* USE_SPI_CRC */
    uint32_t tickstart;
    HAL_StatusTypeDef errorcode = HAL_OK;

    if ((pHSpi->Init.Mode == SPI_MODE_MASTER) && (pHSpi->Init.Direction == SPI_DIRECTION_2LINES))
    {
        pHSpi->State = HAL_SPI_STATE_BUSY_RX;
        return HAL_SPI_TransmitReceive(pHSpi, pData, pData, Size, Timeout);
    }

    tickstart = HAL_GetTick();

    if ((!pData) || (!Size))
        return HAL_ERROR;

    if (pHSpi->State != HAL_SPI_STATE_READY)
        return HAL_BUSY;

    __HAL_LOCK(pHSpi);

    pHSpi->State       = HAL_SPI_STATE_BUSY_RX;
    pHSpi->ErrorCode   = HAL_SPI_ERROR_NONE;
    pHSpi->pRxBuffPtr  = (uint8_t *)pData;
    pHSpi->RxXferSize  = Size;
    pHSpi->RxXferCount = Size;

    pHSpi->pTxBuffPtr  = (uint8_t *)NULL;
    pHSpi->TxXferSize  = 0U;
    pHSpi->TxXferCount = 0U;
    pHSpi->RxISR       = NULL;
    pHSpi->TxISR       = NULL;

#if (USE_SPI_CRC != 0U)
    /* Reset CRC Calculation */
    if (pHSpi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
    {
        SPI_RESET_CRC(pHSpi);
        pHSpi->RxXferCount--;
    }
#endif /* USE_SPI_CRC */

    if (pHSpi->Init.Direction == SPI_DIRECTION_1LINE)
    {
        /* Disable SPI Peripheral before set 1Line direction (BIDIOE bit) */
        CLEAR_BIT(pHSpi->Instance->CR1, SPI_CR1_SPE);
        SPI_1LINE_RX(pHSpi);
    }

    /* Check if the SPI is already enabled. If not, enable SPI*/
    if ((pHSpi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
    {
        CORRECT_SPI_ENABLE();
    }

    if (pHSpi->Init.DataSize == SPI_DATASIZE_8BIT)
    {
        /* Receive data in 8 Bit mode */
        while (pHSpi->RxXferCount > 0U)
        {
            _SPI_Rx_DisableSpi(pHSpi);
            /* Check the RXNE flag */
            if (__HAL_SPI_GET_FLAG(pHSpi, SPI_FLAG_RXNE))
            {
                (* (uint8_t *)pHSpi->pRxBuffPtr) = *(__IO uint8_t *)&pHSpi->Instance->DR;
                pHSpi->pRxBuffPtr += sizeof(uint8_t);
                pHSpi->RxXferCount--;
            }
            else
            {
                /* Timeout management */
                if ((((HAL_GetTick() - tickstart) >=  Timeout) && (Timeout != HAL_MAX_DELAY)) || (Timeout == 0U))
                {
                    errorcode = HAL_TIMEOUT;
                    goto error;
                }
            }
        }
    }
    else
    {
        /* Receive data in 16 Bit mode */
        while (pHSpi->RxXferCount > 0U)
        {
            _SPI_Rx_DisableSpi(pHSpi);

            /* Check the RXNE flag */
            if (__HAL_SPI_GET_FLAG(pHSpi, SPI_FLAG_RXNE))
            {
                *((uint16_t *)pHSpi->pRxBuffPtr) = (uint16_t)pHSpi->Instance->DR;
                pHSpi->pRxBuffPtr += sizeof(uint16_t);
                pHSpi->RxXferCount--;
            }
            else
            {
                /* Timeout management */
                if ((((HAL_GetTick() - tickstart) >=  Timeout) && (Timeout != HAL_MAX_DELAY)) || (Timeout == 0U))
                {
                    errorcode = HAL_TIMEOUT;
                    goto error;
                }
            }
        }
    }

#if (USE_SPI_CRC != 0U)
    /* Handle the CRC Transmission */
    if (pHSpi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
    {
        /* freeze the CRC before the latest data */
        SET_BIT(pHSpi->Instance->CR1, SPI_CR1_CRCNEXT);

        /* Check if CRCNEXT is well reseted by hardware */
        if (READ_BIT(pHSpi->Instance->CR1, SPI_CR1_CRCNEXT))
        {
            /* Workaround to force CRCNEXT bit to zero in case of CRCNEXT is not reset automatically by hardware */
            CLEAR_BIT(pHSpi->Instance->CR1, SPI_CR1_CRCNEXT);
        }
        /* Read the latest data */
        if (_SPI_WaitFlagStateUntilTimeout(pHSpi, SPI_FLAG_RXNE, SET, Timeout, tickstart) != HAL_OK)
        {
            /* the latest data has not been received */
            errorcode = HAL_TIMEOUT;
            goto error;
        }

        /* Receive last data in 16 Bit mode */
        if (pHSpi->Init.DataSize == SPI_DATASIZE_16BIT)
        {
            *((uint16_t *)pHSpi->pRxBuffPtr) = (uint16_t)pHSpi->Instance->DR;
        }
        /* Receive last data in 8 Bit mode */
        else
        {
            (*(uint8_t *)pHSpi->pRxBuffPtr) = *(__IO uint8_t *)&pHSpi->Instance->DR;
        }

        if ((pHSpi->Init.Mode == SPI_MODE_MASTER) &&
            ((pHSpi->Init.Direction == SPI_DIRECTION_1LINE) || (pHSpi->Init.Direction == SPI_DIRECTION_2LINES_RXONLY)))
        {
            /* Disable SPI */
            CLEAR_BIT(pHSpi->Instance->CR1, SPI_CR1_SPE);
        }

        /* Wait the CRC data */
        if (_SPI_WaitFlagStateUntilTimeout(pHSpi, SPI_FLAG_RXNE, SET, Timeout, tickstart) != HAL_OK)
        {
            SET_BIT(pHSpi->ErrorCode, HAL_SPI_ERROR_CRC);
            errorcode = HAL_TIMEOUT;
            goto error;
        }

        tmpreg = READ_REG(pHSpi->Instance->DR);
        UNUSED(tmpreg);
    }
#endif /* USE_SPI_CRC */

    /* Check the end of the transaction */
    if (_SPI_EndRxTransaction(pHSpi, Timeout, tickstart) != HAL_OK)
    {
        pHSpi->ErrorCode = HAL_SPI_ERROR_FLAG;
    }

#if (USE_SPI_CRC != 0U)
    /* Check if CRC error occurred */
    if (__HAL_SPI_GET_FLAG(pHSpi, SPI_FLAG_CRCERR) != RESET)
    {
        SET_BIT(pHSpi->ErrorCode, HAL_SPI_ERROR_CRC);

        SPI_RESET_CRC(pHSpi);
    }
#endif /* USE_SPI_CRC */

    if (pHSpi->ErrorCode != HAL_SPI_ERROR_NONE)
    {
        errorcode = HAL_ERROR;
    }

error :
    pHSpi->State = HAL_SPI_STATE_READY;
    __HAL_UNLOCK(pHSpi);
    return errorcode;
}

/**
  * @brief  HAL_SPI_TransmitReceive
  *             Transmit and Receive an amount of data in blocking mode.
  * @param  [in] pHSpi       Pointer to a SPI_HandleTypeDef structure that contains
  *                         the configuration information for SPI module.
  * @param  [in] pTxData    Pointer to transmission data buffer
  * @param  [in] pRxData    Pointer to reception data buffer
  * @param  [in] Size       Amount of data to be sent and received
  * @param  [in] Timeout    Timeout duration
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_SPI_TransmitReceive(SPI_HandleTypeDef *pHSpi, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size,
                                          uint32_t Timeout)
{
    uint16_t             initial_TxXferCount = 0;
    uint32_t             tickstart = 0;
    uint32_t             txallowed = 1U;
    HAL_StatusTypeDef    errorcode = HAL_OK;

#if (USE_SPI_CRC != 0U)
    __IO uint32_t tmpreg = 0U;
#endif /* USE_SPI_CRC */

    assert_param(IS_SPI_DIRECTION_2LINES(pHSpi->Init.Direction));

    tickstart = HAL_GetTick();

    if ((!pTxData) || (!pRxData) || (!Size))
        return HAL_ERROR;


    if (!((pHSpi->State == HAL_SPI_STATE_READY) || \
        ((pHSpi->Init.Mode == SPI_MODE_MASTER) && (pHSpi->Init.Direction == SPI_DIRECTION_2LINES) && (pHSpi->State == HAL_SPI_STATE_BUSY_RX))))
        return HAL_BUSY;

    __HAL_LOCK(pHSpi);

    initial_TxXferCount = Size;

    /* Don't overwrite in case of HAL_SPI_STATE_BUSY_RX */
    if (pHSpi->State != HAL_SPI_STATE_BUSY_RX)
    {
        pHSpi->State = HAL_SPI_STATE_BUSY_TX_RX;
    }

    pHSpi->ErrorCode   = HAL_SPI_ERROR_NONE;
    pHSpi->pRxBuffPtr  = (uint8_t *)pRxData;
    pHSpi->RxXferCount = Size;
    pHSpi->RxXferSize  = Size;
    pHSpi->pTxBuffPtr  = (uint8_t *)pTxData;
    pHSpi->TxXferCount = Size;
    pHSpi->TxXferSize  = Size;

    pHSpi->RxISR       = NULL;
    pHSpi->TxISR       = NULL;

#if (USE_SPI_CRC != 0U)
    /* Reset CRC Calculation */
    if (pHSpi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
    {
        SPI_RESET_CRC(pHSpi);
    }
#endif /* USE_SPI_CRC */

    /* Check if the SPI is already enabled. If not, enable SPI */
    if ((pHSpi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
    {
        CORRECT_SPI_ENABLE();
    }

    /* Transmit and Receive data in 16 Bit mode */
    if (pHSpi->Init.DataSize == SPI_DATASIZE_16BIT)
    {
        if ((pHSpi->Init.Mode == SPI_MODE_SLAVE) || (initial_TxXferCount == 0x01U))
        {
            pHSpi->Instance->DR = *((uint16_t *)pHSpi->pTxBuffPtr);
            pHSpi->pTxBuffPtr += sizeof(uint16_t);
            pHSpi->TxXferCount--;
        }
        while ((pHSpi->TxXferCount > 0U) || (pHSpi->RxXferCount > 0U))
        {
            /* Check TXE flag */
            if ((__HAL_SPI_GET_FLAG(pHSpi, SPI_FLAG_TXE)) && (pHSpi->TxXferCount > 0U) && (txallowed == 1U))
            {
                pHSpi->Instance->DR = *((uint16_t *)pHSpi->pTxBuffPtr);
                pHSpi->pTxBuffPtr += sizeof(uint16_t);
                pHSpi->TxXferCount--;
                /* Next Data is a reception (Rx). Tx not allowed */
                txallowed = 0U;
            }

            /* Check RXNE flag */
            if ((__HAL_SPI_GET_FLAG(pHSpi, SPI_FLAG_RXNE)) && (pHSpi->RxXferCount > 0U))
            {
                *((uint16_t *)pHSpi->pRxBuffPtr) = (uint16_t)pHSpi->Instance->DR;
                pHSpi->pRxBuffPtr += sizeof(uint16_t);
                pHSpi->RxXferCount--;
                /* Next Data is a Transmission (Tx). Tx is allowed */
                txallowed = 1U;

#if (USE_SPI_CRC != 0U)
                /* Enable CRC Transmission */
                if ((pHSpi->RxXferCount == 1U) && (pHSpi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE))
                {
                    SET_BIT(pHSpi->Instance->CR1, SPI_CR1_CRCNEXT);
                }
#endif /* USE_SPI_CRC */
            }

            if (((HAL_GetTick() - tickstart) >=  Timeout) && (Timeout != HAL_MAX_DELAY))
            {
                errorcode = HAL_TIMEOUT;
                goto error;
            }
        }
    }
    /* Transmit and Receive data in 8 Bit mode */
    else
    {
        if ((pHSpi->Init.Mode == SPI_MODE_SLAVE) || (initial_TxXferCount == 0x01U))
        {
            *((__IO uint8_t *)&pHSpi->Instance->DR) = (*pHSpi->pTxBuffPtr);
            pHSpi->pTxBuffPtr += sizeof(uint8_t);
            pHSpi->TxXferCount--;
        }
        while ((pHSpi->TxXferCount > 0U) || (pHSpi->RxXferCount > 0U))
        {
            /* Check TXE flag */
            if ((__HAL_SPI_GET_FLAG(pHSpi, SPI_FLAG_TXE)) && (pHSpi->TxXferCount > 0U) && (txallowed == 1U))
            {
                *(__IO uint8_t *)&pHSpi->Instance->DR = (*pHSpi->pTxBuffPtr);
                pHSpi->pTxBuffPtr++;
                pHSpi->TxXferCount--;
                /* Next Data is a reception (Rx). Tx not allowed */
                txallowed = 0U;
            }

            /* Wait until RXNE flag is reset */
            if ((__HAL_SPI_GET_FLAG(pHSpi, SPI_FLAG_RXNE)) && (pHSpi->RxXferCount > 0U))
            {
                (*(uint8_t *)pHSpi->pRxBuffPtr) = pHSpi->Instance->DR;
                pHSpi->pRxBuffPtr++;
                pHSpi->RxXferCount--;
                /* Next Data is a Transmission (Tx). Tx is allowed */
                txallowed = 1U;

#if (USE_SPI_CRC != 0U)
                /* Enable CRC Transmission */
                if ((pHSpi->RxXferCount == 1U) && (pHSpi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE))
                {
                SET_BIT(pHSpi->Instance->CR1, SPI_CR1_CRCNEXT);
                }
#endif /* USE_SPI_CRC */
            }

            if ((((HAL_GetTick() - tickstart) >=  Timeout) && ((Timeout != HAL_MAX_DELAY))) || (Timeout == 0U))
            {
                errorcode = HAL_TIMEOUT;
                goto error;
            }
        }
    }

#if (USE_SPI_CRC != 0U)
    /* Read CRC from DR to close CRC calculation process */
    if (pHSpi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
    {
        /* Wait until TXE flag */
        if (_SPI_WaitFlagStateUntilTimeout(pHSpi, SPI_FLAG_RXNE, SET, Timeout, tickstart) != HAL_OK)
        {
            SET_BIT(pHSpi->ErrorCode, HAL_SPI_ERROR_CRC);
            errorcode = HAL_TIMEOUT;
            goto error;
        }
        tmpreg = READ_REG(pHSpi->Instance->DR);
        UNUSED(tmpreg);
    }

    /* Check if CRC error occurred */
    if (__HAL_SPI_GET_FLAG(pHSpi, SPI_FLAG_CRCERR) != RESET)
    {
        SET_BIT(pHSpi->ErrorCode, HAL_SPI_ERROR_CRC);

        SPI_RESET_CRC(pHSpi);

        errorcode = HAL_ERROR;
    }
#endif /* USE_SPI_CRC */

    /* Check the end of the transaction */
    if (_SPI_EndRxTxTransaction(pHSpi, Timeout, tickstart) != HAL_OK)
    {
        errorcode = HAL_ERROR;
        pHSpi->ErrorCode = HAL_SPI_ERROR_FLAG;
        goto error;
    }

    /* Clear overrun flag in 2 Lines communication mode because received is not read */
    if (pHSpi->Init.Direction == SPI_DIRECTION_2LINES)
    {
        __HAL_SPI_CLEAR_OVRFLAG(pHSpi);
    }

error :
    pHSpi->State = HAL_SPI_STATE_READY;
    __HAL_UNLOCK(pHSpi);
    return errorcode;
}

/**
  * @brief  HAL_SPI_Transmit_IT
  *             Transmit an amount of data in non-blocking mode with Interrupt.
  * @param  [in] pHSpi       Pointer to a SPI_HandleTypeDef structure that contains
  *                         the configuration information for SPI module.
  * @param  [in] pData      Pointer to data buffer
  * @param  [in] Size       Amount of data to be sent
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_SPI_Transmit_IT(SPI_HandleTypeDef *pHSpi, uint8_t *pData, uint16_t Size)
{
    assert_param(IS_SPI_DIRECTION_2LINES_OR_1LINE(pHSpi->Init.Direction));

    if ((!pData) || (!Size))
        return HAL_ERROR;

    if (pHSpi->State != HAL_SPI_STATE_READY)
        return HAL_BUSY;

    __HAL_LOCK(pHSpi);

    pHSpi->State       = HAL_SPI_STATE_BUSY_TX;
    pHSpi->ErrorCode   = HAL_SPI_ERROR_NONE;
    pHSpi->pTxBuffPtr  = (uint8_t *)pData;
    pHSpi->TxXferSize  = Size;
    pHSpi->TxXferCount = Size;

    pHSpi->pRxBuffPtr  = (uint8_t *)NULL;
    pHSpi->RxXferSize  = 0U;
    pHSpi->RxXferCount = 0U;
    pHSpi->RxISR       = NULL;

    /* Set the function for IT treatment */
    if (pHSpi->Init.DataSize > SPI_DATASIZE_8BIT)
    {
        pHSpi->TxISR = _SPI_TxISR_16BIT;
    }
    else
    {
        pHSpi->TxISR = _SPI_TxISR_8BIT;
    }

    if (pHSpi->Init.Direction == SPI_DIRECTION_1LINE)
    {
        /* Disable SPI Peripheral before set 1Line direction (BIDIOE bit) */
        CLEAR_BIT(pHSpi->Instance->CR1, SPI_CR1_SPE);
        SPI_1LINE_TX(pHSpi);
    }

#if (USE_SPI_CRC != 0U)
    /* Reset CRC Calculation */
    if (pHSpi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
    {
        SPI_RESET_CRC(pHSpi);
    }
#endif /* USE_SPI_CRC */

    /* Enable TXE and ERR interrupt */
    SET_BIT(pHSpi->Instance->CR2, (SPI_IT_TXE | SPI_IT_ERR));

    /* Check if the SPI is already enabled. If not, enable SPI */
    if ((pHSpi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
    {
        CORRECT_SPI_ENABLE();
    }

    __HAL_UNLOCK(pHSpi);
    return HAL_OK;
}

/**
  * @brief  HAL_SPI_Receive_IT
  *             Receive an amount of data in non-blocking mode with Interrupt.
  * @param  [in] pHSpi       Pointer to a SPI_HandleTypeDef structure that contains
  *               the       configuration information for SPI module.
  * @param  [in] pData      Pointer to data buffer
  * @param  [in] Size       Amount of data to be sent
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_SPI_Receive_IT(SPI_HandleTypeDef *pHSpi, uint8_t *pData, uint16_t Size)
{
    if ((pHSpi->Init.Direction == SPI_DIRECTION_2LINES) && (pHSpi->Init.Mode == SPI_MODE_MASTER))
    {
        pHSpi->State = HAL_SPI_STATE_BUSY_RX;
        return HAL_SPI_TransmitReceive_IT(pHSpi, pData, pData, Size);
    }

    if ((!pData) || (!Size))
        return HAL_ERROR;

    if (pHSpi->State != HAL_SPI_STATE_READY)
        return HAL_BUSY;

    __HAL_LOCK(pHSpi);

    pHSpi->State       = HAL_SPI_STATE_BUSY_RX;
    pHSpi->ErrorCode   = HAL_SPI_ERROR_NONE;
    pHSpi->pRxBuffPtr  = (uint8_t *)pData;
    pHSpi->RxXferSize  = Size;
    pHSpi->RxXferCount = Size;

    pHSpi->pTxBuffPtr  = (uint8_t *)NULL;
    pHSpi->TxXferSize  = 0U;
    pHSpi->TxXferCount = 0U;
    pHSpi->TxISR       = NULL;

    if (pHSpi->Init.DataSize > SPI_DATASIZE_8BIT)
    {
        pHSpi->RxISR = _SPI_RxISR_16BIT;
    }
    else
    {
        pHSpi->RxISR = _SPI_RxISR_8BIT;
    }

    if (pHSpi->Init.Direction == SPI_DIRECTION_1LINE)
    {
        /* Disable SPI Peripheral before set 1Line direction (BIDIOE bit) */
        CLEAR_BIT(pHSpi->Instance->CR1, SPI_CR1_SPE);
        SPI_1LINE_RX(pHSpi);
    }

#if (USE_SPI_CRC != 0U)
    if (pHSpi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
    {
        SPI_RESET_CRC(pHSpi);
    }
#endif /* USE_SPI_CRC */

    /* Enable TXE and ERR interrupt */
    SET_BIT(pHSpi->Instance->CR2, (SPI_IT_RXNE | SPI_IT_ERR));

    /* Check if the SPI is already enabled. If not, enable SPI */
    if ((pHSpi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
    {
        CORRECT_SPI_ENABLE();
    }

    __HAL_UNLOCK(pHSpi);
    return HAL_OK;
}

/**
  * @brief  HAL_SPI_TransmitReceive_IT
  *             Transmit and Receive an amount of data in non-blocking mode with Interrupt.
  * @param  [in] pHSpi       Pointer to a SPI_HandleTypeDef structure that contains
  *                         the configuration information for SPI module.
  * @param  [in] pTxData    Pointer to transmission data buffer
  * @param  [in] pRxData    Pointer to reception data buffer
  * @param  [in] Size       Amount of data to be sent and received
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_SPI_TransmitReceive_IT(SPI_HandleTypeDef *pHSpi, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size)
{
    assert_param(IS_SPI_DIRECTION_2LINES(pHSpi->Init.Direction));

    if ((!pTxData) || (!pRxData) || (!Size))
        return HAL_ERROR;

    if (!((pHSpi->State == HAL_SPI_STATE_READY) || \
        ((pHSpi->Init.Mode == SPI_MODE_MASTER) && (pHSpi->Init.Direction == SPI_DIRECTION_2LINES) && (pHSpi->State == HAL_SPI_STATE_BUSY_RX))))
        return HAL_BUSY;

    __HAL_LOCK(pHSpi);

    /* Don't overwrite in case of HAL_SPI_STATE_BUSY_RX */
    if (pHSpi->State != HAL_SPI_STATE_BUSY_RX)
    {
        pHSpi->State = HAL_SPI_STATE_BUSY_TX_RX;
    }

    pHSpi->ErrorCode   = HAL_SPI_ERROR_NONE;
    pHSpi->pTxBuffPtr  = (uint8_t *)pTxData;
    pHSpi->TxXferSize  = Size;
    pHSpi->TxXferCount = Size;
    pHSpi->pRxBuffPtr  = (uint8_t *)pRxData;
    pHSpi->RxXferSize  = Size;
    pHSpi->RxXferCount = Size;

    if (pHSpi->Init.DataSize > SPI_DATASIZE_8BIT)
    {
        pHSpi->RxISR     = _SPI_2linesRxISR_16BIT;
        pHSpi->TxISR     = _SPI_2linesTxISR_16BIT;
    }
    else
    {
        pHSpi->RxISR     = _SPI_2linesRxISR_8BIT;
        pHSpi->TxISR     = _SPI_2linesTxISR_8BIT;
    }

#if (USE_SPI_CRC != 0U)
    /* Reset CRC Calculation */
    if (pHSpi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
    {
        SPI_RESET_CRC(pHSpi);
    }
#endif /* USE_SPI_CRC */

    /* Enable TXE, RXNE and ERR interrupt */
    SET_BIT(pHSpi->Instance->CR2, (SPI_IT_TXE | SPI_IT_RXNE | SPI_IT_ERR));

    /* Check if the SPI is already enabled. If not, enable SPI */
    if ((pHSpi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
    {
        CORRECT_SPI_ENABLE();
    }

    __HAL_UNLOCK(pHSpi);
    return HAL_OK;
}


/**
  * @brief  HAL_SPI_Abort
  *             Abort ongoing transfer (blocking mode).
  * @param  [in] pHSpi       SPI handle.
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_SPI_Abort(SPI_HandleTypeDef *pHSpi)
{
    HAL_StatusTypeDef errorcode = HAL_OK;
    __IO uint32_t count = 0;
    __IO uint32_t resetcount = 0;

    resetcount = SPI_DEFAULT_TIMEOUT * (SystemCoreClock / 24U / 1000U);
    count = resetcount;

    /* Clear ERRIE interrupt to avoid error interrupts generation during Abort procedure */
    CLEAR_BIT(pHSpi->Instance->CR2, SPI_CR2_ERRIE);

    /* Disable TXEIE, RXNEIE and ERRIE(mode fault event, overrun error, TI frame error) interrupts */
    if (HAL_IS_BIT_SET(pHSpi->Instance->CR2, SPI_CR2_TXEIE))
    {
        pHSpi->TxISR = _SPI_AbortTx_ISR;
        /* Wait HAL_SPI_STATE_ABORT state */
        do
        {
            if (count == 0U)
            {
                SET_BIT(pHSpi->ErrorCode, HAL_SPI_ERROR_ABORT);
                break;
            }
            count--;
        } while (pHSpi->State != HAL_SPI_STATE_ABORT);
        count = resetcount;
    }

    if (HAL_IS_BIT_SET(pHSpi->Instance->CR2, SPI_CR2_RXNEIE))
    {
        pHSpi->RxISR = _SPI_AbortRx_ISR;
        /* Wait HAL_SPI_STATE_ABORT state */
        do
        {
            if (count == 0U)
            {
                SET_BIT(pHSpi->ErrorCode, HAL_SPI_ERROR_ABORT);
                break;
            }
            count--;
        } while (pHSpi->State != HAL_SPI_STATE_ABORT);
        count = resetcount;
    }

    pHSpi->RxXferCount = 0U;
    pHSpi->TxXferCount = 0U;

    if (pHSpi->ErrorCode == HAL_SPI_ERROR_ABORT)
    {
        errorcode = HAL_ERROR;
    }
    else
    {
        pHSpi->ErrorCode = HAL_SPI_ERROR_NONE;
    }

    __HAL_SPI_CLEAR_OVRFLAG(pHSpi);

    pHSpi->State = HAL_SPI_STATE_READY;

    return errorcode;
}

/**
  * @brief  HAL_SPI_Abort_IT
  *             Abort ongoing transfer (Interrupt mode).
  * @param  [in] pHSpi : SPI handle.
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_SPI_Abort_IT(SPI_HandleTypeDef *pHSpi)
{
    HAL_StatusTypeDef errorcode = HAL_OK;
    __IO uint32_t count = 0;
    __IO uint32_t resetcount = 0;

    resetcount = SPI_DEFAULT_TIMEOUT * (SystemCoreClock / 24U / 1000U);
    count = resetcount;

    /* Clear ERRIE interrupt to avoid error interrupts generation during Abort procedure */
    CLEAR_BIT(pHSpi->Instance->CR2, SPI_CR2_ERRIE);

    if (HAL_IS_BIT_SET(pHSpi->Instance->CR2, SPI_CR2_TXEIE))
    {
        pHSpi->TxISR = _SPI_AbortTx_ISR;
        /* Wait HAL_SPI_STATE_ABORT state */
        do
        {
            if (count == 0U)
            {
                SET_BIT(pHSpi->ErrorCode, HAL_SPI_ERROR_ABORT);
                break;
            }
            count--;
        } while (pHSpi->State != HAL_SPI_STATE_ABORT);
        count = resetcount;
    }

    if (HAL_IS_BIT_SET(pHSpi->Instance->CR2, SPI_CR2_RXNEIE))
    {
        pHSpi->RxISR = _SPI_AbortRx_ISR;
        /* Wait HAL_SPI_STATE_ABORT state */
        do
        {
            if (count == 0U)
            {
                SET_BIT(pHSpi->ErrorCode, HAL_SPI_ERROR_ABORT);
                break;
            }
            count--;
        } while (pHSpi->State != HAL_SPI_STATE_ABORT);
        count = resetcount;
    }

    pHSpi->RxXferCount = 0U;
    pHSpi->TxXferCount = 0U;

    if (pHSpi->ErrorCode == HAL_SPI_ERROR_ABORT)
    {
        errorcode = HAL_ERROR;
    }
    else
    {
        pHSpi->ErrorCode = HAL_SPI_ERROR_NONE;
    }

    __HAL_SPI_CLEAR_OVRFLAG(pHSpi);

    pHSpi->State = HAL_SPI_STATE_READY;

    HAL_SPI_AbortCpltCallback(pHSpi);

    return errorcode;
}


/**
  * @brief  HAL_SPI_Transmit_DMA
  *             Transmit an amount of data in non-blocking mode with DMA.
  * @param  [in] pHSpi          Pointer to a SPI_HandleTypeDef structure that contains
  *                             the configuration information for SPI module.
  * @param  [in] pData          Pointer to data buffer
  * @param  [in] Size           Amount of data to be sent
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_SPI_Transmit_DMA(SPI_HandleTypeDef *pHSpi, uint8_t *pData, uint16_t Size)
{
    HAL_StatusTypeDef               errorcode = HAL_OK;
    HAL_DMA_Descriptor_Cfg_TypeDef  desc_cfg;
    DMA_Data_Inc_t                  increment;
    DMA_Data_Size_t                 data_size;

    assert_param(IS_SPI_DIRECTION_2LINES_OR_1LINE(pHSpi->Init.Direction));

    if (pHSpi->State != HAL_SPI_STATE_READY)
        return HAL_BUSY;

    if ((!pData) || (!Size))
        return HAL_ERROR;

    __HAL_LOCK(pHSpi);

    /* Set the transaction information */
    pHSpi->State       = HAL_SPI_STATE_BUSY_TX;
    pHSpi->ErrorCode   = HAL_SPI_ERROR_NONE;
    pHSpi->pTxBuffPtr  = (uint8_t *)pData;
    pHSpi->TxXferSize  = Size;
    pHSpi->TxXferCount = Size;

    /* Init field not used in handle to zero */
    pHSpi->pRxBuffPtr  = (uint8_t *)NULL;
    pHSpi->TxISR       = NULL;
    pHSpi->RxISR       = NULL;
    pHSpi->RxXferSize  = 0U;
    pHSpi->RxXferCount = 0U;

    /* Configure communication direction : 1Line */
    if (pHSpi->Init.Direction == SPI_DIRECTION_1LINE)
    {
        /* Disable SPI Peripheral before set 1Line direction (BIDIOE bit) */
        __HAL_SPI_DISABLE(pHSpi);
        SPI_1LINE_TX(pHSpi);
    }

#if (USE_SPI_CRC != 0U)
    /* Reset CRC Calculation */
    if (pHSpi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
    {
        __HAL_SPI_DISABLE(pHSpi);
        SPI_RESET_CRC(pHSpi);
    }
#endif /* USE_SPI_CRC */

    if(pHSpi->Init.DataSize == SPI_DATASIZE_8BIT)
    {
        increment  = DMA_DATA_INC_BYTE;
        data_size = DMA_DATA_SIZE_BYTE;
    }
    else
    {
        increment  = DMA_DATA_INC_HALFWORD;
        data_size = DMA_DATA_SIZE_HALFWORD;
        Size <<= 1;
    }

    /* Enable the Tx DMA Stream/Channel */
    desc_cfg.type           = DMA_DESCRIPTOR_TYPE_PRIMARY;
    desc_cfg.mode           = HAL_DMA_Mode_STOP;
    desc_cfg.src_addr       = pData;
    desc_cfg.dst_addr       = (void *)&(pHSpi->Instance->DR);
    desc_cfg.xfer_bytes     = Size;
    desc_cfg.src_inc        = increment;
    desc_cfg.dst_inc        = DMA_DATA_INC_NONE;
    desc_cfg.unit_size      = data_size;
    desc_cfg.arbit_rate     = DMA_ARBITRATION_RATE_1;
    desc_cfg.timeout        = -1;
    if (HAL_OK != _SPI_DMA_Config(pHSpi->pHDMA, HAL_DMA_CHANNEL_SPI_I2S_TX,&desc_cfg))
    {
        SET_BIT(pHSpi->ErrorCode, HAL_SPI_ERROR_DMA);
        errorcode = HAL_ERROR;

        pHSpi->State = HAL_SPI_STATE_READY;
        goto error;
    }

    /* Check if the SPI is already enabled */
    if ((pHSpi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
    {
        /* Enable SPI peripheral */
        CORRECT_SPI_ENABLE();
    }

    /* Enable Tx DMA Request */
    SET_BIT(pHSpi->Instance->CR2, SPI_CR2_TXDMAEN);

error :
    __HAL_UNLOCK(pHSpi);
    return errorcode;
}

/**
  * @brief  HAL_SPI_Receive_DMA
  *             Receive an amount of data in non-blocking mode with DMA.
  * @param  [in] pHSpi          Pointer to a SPI_HandleTypeDef structure that contains
  *                             the configuration information for SPI module.
  * @param  [in] pData          Pointer to data buffer
  * @param  [in] Size           Amount of data to be sent
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_SPI_Receive_DMA(SPI_HandleTypeDef *pHSpi, uint8_t *pData, uint16_t Size)
{
    HAL_DMA_Descriptor_Cfg_TypeDef  desc_cfg;
    HAL_StatusTypeDef               errorcode = HAL_OK;
    DMA_Data_Inc_t                  increment;
    DMA_Data_Size_t                 data_size;

    if ((pHSpi->Init.Direction == SPI_DIRECTION_2LINES) && (pHSpi->Init.Mode == SPI_MODE_MASTER))
    {
        pHSpi->State = HAL_SPI_STATE_BUSY_RX;

        /* Call transmit-receive function to send Dummy data on Tx line and generate clock on CLK line */
        return HAL_SPI_TransmitReceive_DMA(pHSpi, pData, pData, Size);
    }

    if (pHSpi->State != HAL_SPI_STATE_READY)
        return HAL_BUSY;

    if ((!pData) || (!Size))
        return HAL_ERROR;

    __HAL_LOCK(pHSpi);

    /* Set the transaction information */
    pHSpi->State       = HAL_SPI_STATE_BUSY_RX;
    pHSpi->ErrorCode   = HAL_SPI_ERROR_NONE;
    pHSpi->pRxBuffPtr  = (uint8_t *)pData;
    pHSpi->RxXferSize  = Size;
    pHSpi->RxXferCount = Size;

    /*Init field not used in handle to zero */
    pHSpi->RxISR       = NULL;
    pHSpi->TxISR       = NULL;
    pHSpi->TxXferSize  = 0U;
    pHSpi->TxXferCount = 0U;

    /* Configure communication direction : 1Line */
    if (pHSpi->Init.Direction == SPI_DIRECTION_1LINE)
    {
        /* Disable SPI Peripheral before set 1Line direction (BIDIOE bit) */
        __HAL_SPI_DISABLE(pHSpi);
        SPI_1LINE_RX(pHSpi);
    }

#if (USE_SPI_CRC != 0U)
    /* Reset CRC Calculation */
    if (pHSpi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
    {
        __HAL_SPI_DISABLE(pHSpi);
        SPI_RESET_CRC(pHSpi);
    }
#endif /* USE_SPI_CRC */

    if(pHSpi->Init.DataSize == SPI_DATASIZE_8BIT)
    {
        increment  = DMA_DATA_INC_BYTE;
        data_size = DMA_DATA_SIZE_BYTE;
    }
    else
    {
        increment  = DMA_DATA_INC_HALFWORD;
        data_size = DMA_DATA_SIZE_HALFWORD;
        Size <<= 1;
    }

    /* Enable the Rx DMA Stream/Channel  */
    desc_cfg.type           = DMA_DESCRIPTOR_TYPE_PRIMARY;
    desc_cfg.mode           = HAL_DMA_Mode_STOP;
    desc_cfg.src_addr       = (void *)&(pHSpi->Instance->DR);
    desc_cfg.dst_addr       = pData;
    desc_cfg.xfer_bytes     = Size;
    desc_cfg.src_inc        = DMA_DATA_INC_NONE;
    desc_cfg.dst_inc        = increment;
    desc_cfg.unit_size      = data_size;
    desc_cfg.arbit_rate     = DMA_ARBITRATION_RATE_1;
    desc_cfg.timeout        = -1;

    if (HAL_OK != _SPI_DMA_Config(pHSpi->pHDMA, HAL_DMA_CHANNEL_SPI_I2S_RX,&desc_cfg))
    {
        SET_BIT(pHSpi->ErrorCode, HAL_SPI_ERROR_DMA);
        errorcode = HAL_ERROR;

        pHSpi->State = HAL_SPI_STATE_READY;
        goto error;
    }

    /* Check if the SPI is already enabled */
    if ((pHSpi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
    {
        /* Enable SPI peripheral */
        CORRECT_SPI_ENABLE();
    }

    /* Enable Rx DMA Request */
    SET_BIT(pHSpi->Instance->CR2, SPI_CR2_RXDMAEN);

error:
    __HAL_UNLOCK(pHSpi);
    return errorcode;
}



/**
  * @brief  HAL_SPI_TransmitReceive_DMA
  *             Transmit and Receive an amount of data in non-blocking mode with DMA.
  * @param  [in] pHSpi          Pointer to a SPI_HandleTypeDef structure that contains
  *                             the configuration information for SPI module.
  * @param  [in] pTxData        Pointer to transmission data buffer
  * @param  [in] pRxData        Pointer to reception data buffer
  * @param  [in] Size           Amount of data to be sent
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_SPI_TransmitReceive_DMA(SPI_HandleTypeDef *pHSpi, uint8_t *pTxData, uint8_t *pRxData,uint16_t Size)
{
    uint32_t                        tmp_mode;
    HAL_SPI_StateTypeDef            tmp_state;
    HAL_DMA_Descriptor_Cfg_TypeDef  desc_cfg;
    HAL_StatusTypeDef               errorcode = HAL_OK;
    DMA_Data_Inc_t                  increment;
    DMA_Data_Size_t                 data_size;

    assert_param(IS_SPI_DIRECTION_2LINES(pHSpi->Init.Direction));

    /* Init temporary variables */
    tmp_state           = pHSpi->State;
    tmp_mode            = pHSpi->Init.Mode;

    if (!((tmp_state == HAL_SPI_STATE_READY) ||
        ((tmp_mode == SPI_MODE_MASTER) && (pHSpi->Init.Direction == SPI_DIRECTION_2LINES) && (tmp_state == HAL_SPI_STATE_BUSY_RX))))
        return HAL_BUSY;

    if ((!pTxData) || (!pRxData) || (!Size))
        return HAL_ERROR;

    __HAL_LOCK(pHSpi);

    /* Don't overwrite in case of HAL_SPI_STATE_BUSY_RX */
    if (pHSpi->State != HAL_SPI_STATE_BUSY_RX)
    {
        pHSpi->State = HAL_SPI_STATE_BUSY_TX_RX;
    }

    /* Set the transaction information */
    pHSpi->ErrorCode   = HAL_SPI_ERROR_NONE;
    pHSpi->pTxBuffPtr  = (uint8_t *)pTxData;
    pHSpi->TxXferSize  = Size;
    pHSpi->TxXferCount = Size;
    pHSpi->pRxBuffPtr  = (uint8_t *)pRxData;
    pHSpi->RxXferSize  = Size;
    pHSpi->RxXferCount = Size;

    /* Init field not used in handle to zero */
    pHSpi->RxISR       = NULL;
    pHSpi->TxISR       = NULL;

#if (USE_SPI_CRC != 0U)
    /* Reset CRC Calculation */
    if (pHSpi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
    {
        __HAL_SPI_DISABLE(pHSpi);
        SPI_RESET_CRC(pHSpi);
    }
#endif /* USE_SPI_CRC */

    if(pHSpi->Init.DataSize == SPI_DATASIZE_8BIT)
    {
        increment  = DMA_DATA_INC_BYTE;
        data_size = DMA_DATA_SIZE_BYTE;
    }
    else
    {
        increment  = DMA_DATA_INC_HALFWORD;
        data_size = DMA_DATA_SIZE_HALFWORD;
        Size <<= 1;
    }

    /* Enable the Rx DMA Stream/Channel  */
    desc_cfg.type           = DMA_DESCRIPTOR_TYPE_PRIMARY;
    desc_cfg.mode           = HAL_DMA_Mode_STOP;
    desc_cfg.src_addr       = (void *)&(pHSpi->Instance->DR);
    desc_cfg.dst_addr       = pRxData;
    desc_cfg.xfer_bytes     = Size;
    desc_cfg.src_inc        = DMA_DATA_INC_NONE;
    desc_cfg.dst_inc        = increment;
    desc_cfg.unit_size      = data_size;
    desc_cfg.arbit_rate     = DMA_ARBITRATION_RATE_1;
    desc_cfg.timeout        = -1;

    if (HAL_OK != _SPI_DMA_Config(pHSpi->pHDMA, HAL_DMA_CHANNEL_SPI_I2S_RX,&desc_cfg))
    {
        SET_BIT(pHSpi->ErrorCode, HAL_SPI_ERROR_DMA);
        errorcode = HAL_ERROR;

        pHSpi->State = HAL_SPI_STATE_READY;
        goto error;
    }

    /* Enable the Tx DMA Stream/Channel  */
    desc_cfg.type           = DMA_DESCRIPTOR_TYPE_PRIMARY;
    desc_cfg.mode           = HAL_DMA_Mode_STOP;
    desc_cfg.src_addr       = pTxData;
    desc_cfg.dst_addr       = (void *)&(pHSpi->Instance->DR);
    desc_cfg.xfer_bytes     = Size;
    desc_cfg.src_inc        = increment;
    desc_cfg.dst_inc        = DMA_DATA_INC_NONE;
    desc_cfg.unit_size      = data_size;
    desc_cfg.arbit_rate     = DMA_ARBITRATION_RATE_1;
    desc_cfg.timeout        = -1;
    if (HAL_OK != _SPI_DMA_Config(pHSpi->pHDMA, HAL_DMA_CHANNEL_SPI_I2S_TX,&desc_cfg))
    {
        /* Update SPI error code */
        SET_BIT(pHSpi->ErrorCode, HAL_SPI_ERROR_DMA);
        errorcode = HAL_ERROR;

        pHSpi->State = HAL_SPI_STATE_READY;
        goto error;
    }

    /* Check if the SPI is already enabled */
    if ((pHSpi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
    {
        CORRECT_SPI_ENABLE();
    }

    /* Enable Tx DMA Request */
    SET_BIT(pHSpi->Instance->CR2, SPI_CR2_TXDMAEN);
    SET_BIT(pHSpi->Instance->CR2, SPI_CR2_RXDMAEN);

error :
    __HAL_UNLOCK(pHSpi);
    return errorcode;
}


/**
  * @brief  HAL_SPI_DMAPause
  *             Pause the DMA Transfer.
  * @param  [in] pHSpi       Pointer to a SPI_HandleTypeDef structure that contains
  *                         the configuration information for the specified SPI module.
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_SPI_DMAPause(SPI_HandleTypeDef *pHSpi)
{
    __HAL_LOCK(pHSpi);

    /* Disable the SPI DMA Tx & Rx requests */
    CLEAR_BIT(pHSpi->Instance->CR2, SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN);

    __HAL_UNLOCK(pHSpi);

    return HAL_OK;
}

/**
  * @brief  HAL_SPI_DMAResume
  *             Resume the DMA Transfer.
  * @param  [in] pHSpi       Pointer to a SPI_HandleTypeDef structure that contains
  *                         the configuration information for the specified SPI module.
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_SPI_DMAResume(SPI_HandleTypeDef *pHSpi)
{
    __HAL_LOCK(pHSpi);

    /* Enable the SPI DMA Tx & Rx requests */
    SET_BIT(pHSpi->Instance->CR2, SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN);

    __HAL_UNLOCK(pHSpi);

    return HAL_OK;
}

/**
  * @brief  Stop the DMA Transfer.
  * @param  [in] pHSpi      Pointer to a SPI_HandleTypeDef structure that contains
  *                         the configuration information for the specified SPI module.
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_SPI_DMAStop(SPI_HandleTypeDef *pHSpi)
{
    HAL_StatusTypeDef errorcode = HAL_OK;
    if (pHSpi->pHDMA != NULL)
    {
        /* Abort the SPI DMA tx Stream/Channel  */
        if (HAL_OK != HAL_DMA_Channel_Stop(pHSpi->pHDMA,HAL_DMA_CHANNEL_SPI_I2S_TX))
        {
          SET_BIT(pHSpi->ErrorCode, HAL_SPI_ERROR_DMA);
          errorcode = HAL_ERROR;
        }

        /* Abort the SPI DMA rx Stream/Channel  */
        if (HAL_OK != HAL_DMA_Channel_Stop(pHSpi->pHDMA,HAL_DMA_CHANNEL_SPI_I2S_RX))
        {
          SET_BIT(pHSpi->ErrorCode, HAL_SPI_ERROR_DMA);
          errorcode = HAL_ERROR;
        }
    }

    /* Disable the SPI DMA Tx & Rx requests */
    CLEAR_BIT(pHSpi->Instance->CR2, SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN);
    pHSpi->State = HAL_SPI_STATE_READY;
    return errorcode;
}

/**
  * @brief  HAL_SPI_IRQHandler
  *             Handle SPI interrupt request.
  * @param  [in] pHSpi       Pointer to a SPI_HandleTypeDef structure that contains
  *                         the configuration information for the specified SPI module.
  * @retval None
  */
void HAL_SPI_IRQHandler(SPI_HandleTypeDef *pHSpi)
{
    uint32_t itsource = pHSpi->Instance->CR2;
    uint32_t itflag   = pHSpi->Instance->SR;

    /* SPI in mode Receiver */
    if ((SPI_CHECK_FLAG(itflag, SPI_FLAG_OVR) == RESET) &&
      (SPI_CHECK_FLAG(itflag, SPI_FLAG_RXNE) != RESET) && (SPI_CHECK_IT_SOURCE(itsource, SPI_IT_RXNE) != RESET))
    {
        pHSpi->RxISR(pHSpi);
        return;
    }

    /* SPI in mode Transmitter */
    if ((SPI_CHECK_FLAG(itflag, SPI_FLAG_TXE) != RESET) && (SPI_CHECK_IT_SOURCE(itsource, SPI_IT_TXE) != RESET))
    {
        pHSpi->TxISR(pHSpi);
        return;
    }

    /* SPI in Error Treatment */
    if (((SPI_CHECK_FLAG(itflag, SPI_FLAG_MODF) != RESET) || (SPI_CHECK_FLAG(itflag, SPI_FLAG_OVR) != RESET))
        && (SPI_CHECK_IT_SOURCE(itsource, SPI_IT_ERR) != RESET))
    {
        /* SPI Overrun error interrupt occurred */
        if (SPI_CHECK_FLAG(itflag, SPI_FLAG_OVR) != RESET)
        {
            if (pHSpi->State != HAL_SPI_STATE_BUSY_TX)
            {
                SET_BIT(pHSpi->ErrorCode, HAL_SPI_ERROR_OVR);
                __HAL_SPI_CLEAR_OVRFLAG(pHSpi);
            }
            else
            {
                __HAL_SPI_CLEAR_OVRFLAG(pHSpi);
                return;
            }
        }

        /* SPI Mode Fault error interrupt occurred */
        if (SPI_CHECK_FLAG(itflag, SPI_FLAG_MODF) != RESET)
        {
            SET_BIT(pHSpi->ErrorCode, HAL_SPI_ERROR_MODF);
            __HAL_SPI_CLEAR_MODFFLAG(pHSpi);
        }

        /* SPI Frame error interrupt occurred */
        if (pHSpi->ErrorCode != HAL_SPI_ERROR_NONE)
        {
            /* Disable all interrupts */
            CLEAR_BIT(pHSpi->Instance->CR2, (SPI_IT_RXNE | SPI_IT_TXE | SPI_IT_ERR));

            pHSpi->State = HAL_SPI_STATE_READY;
            /* Disable the SPI DMA requests if enabled */
            if ((HAL_IS_BIT_SET(itsource, SPI_CR2_TXDMAEN)) || (HAL_IS_BIT_SET(itsource, SPI_CR2_RXDMAEN)))
            {
                CLEAR_BIT(pHSpi->Instance->CR2, (SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN));
            }
            else
            {
                HAL_SPI_ErrorCallback(pHSpi);
            }
        }
    return;
    }
}

/**
  * @brief  Initialize the SPI MSP.
  * @param  pHSpi : SPI handle
  * @retval None
  */
__weak void HAL_SPI_MspInit(SPI_HandleTypeDef *pHSpi)
{
    /* Prevent unused argument(s) compilation warning */
    UNUSED(pHSpi);
}

/**
  * @brief  De-Initialize the SPI MSP.
  * @param  pHSpi : SPI handle
  * @retval None
  */
__weak void HAL_SPI_MspDeInit(SPI_HandleTypeDef *pHSpi)
{
    /* Prevent unused argument(s) compilation warning */
    UNUSED(pHSpi);
}

/**
  * @brief  Tx Transfer completed callback.
  * @param  pHSpi : SPI handle
  * @retval None
  */
__weak void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *pHSpi)
{
    /* Prevent unused argument(s) compilation warning */
    UNUSED(pHSpi);
}

/**
  * @brief  Rx Transfer completed callback.
  * @param  pHSpi : SPI handle
  * @retval None
  */
__weak void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *pHSpi)
{
    /* Prevent unused argument(s) compilation warning */
    UNUSED(pHSpi);
}

/**
  * @brief  Tx and Rx Transfer completed callback.
  * @param  pHSpi : SPI handle
  * @retval None
  */
__weak void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *pHSpi)
{
    /* Prevent unused argument(s) compilation warning */
    UNUSED(pHSpi);
}

/**
  * @brief  Tx Half Transfer completed callback.
  * @param  pHSpi : SPI handle
  * @retval None
  */
__weak void HAL_SPI_TxHalfCpltCallback(SPI_HandleTypeDef *pHSpi)
{
    /* Prevent unused argument(s) compilation warning */
    UNUSED(pHSpi);
}

/**
  * @brief  Rx Half Transfer completed callback.
  * @param  pHSpi : SPI handle
  * @retval None
  */
__weak void HAL_SPI_RxHalfCpltCallback(SPI_HandleTypeDef *pHSpi)
{
    /* Prevent unused argument(s) compilation warning */
    UNUSED(pHSpi);
}

/**
  * @brief  Tx and Rx Half Transfer callback.
  * @param  pHSpi : SPI handle
  * @retval None
  */
__weak void HAL_SPI_TxRxHalfCpltCallback(SPI_HandleTypeDef *pHSpi)
{
    /* Prevent unused argument(s) compilation warning */
    UNUSED(pHSpi);
}

/**
  * @brief  SPI error callback.
  * @param  pHSpi : SPI handle
  * @retval None
  */
__weak void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *pHSpi)
{
    /* Prevent unused argument(s) compilation warning */
    UNUSED(pHSpi);
}

/**
  * @brief  SPI Abort Complete callback.
  * @param  pHSpi : SPI handle
  * @retval None
  */
__weak void HAL_SPI_AbortCpltCallback(SPI_HandleTypeDef *pHSpi)
{
    /* Prevent unused argument(s) compilation warning */
    UNUSED(pHSpi);
}

/**
  * @brief  Return the SPI handle state.
  * @param  pHSpi pointer to a SPI_HandleTypeDef structure that contains
  *               the configuration information for SPI module.
  * @retval SPI state
  */
HAL_SPI_StateTypeDef HAL_SPI_GetState(SPI_HandleTypeDef *pHSpi)
{
    /* Return SPI handle state */
    return pHSpi->State;
}

/**
  * @brief  Return the SPI error code.
  * @param  pHSpi pointer to a SPI_HandleTypeDef structure that contains
  *               the configuration information for SPI module.
  * @retval SPI error code in bitmap format
  */
uint32_t HAL_SPI_GetError(SPI_HandleTypeDef *pHSpi)
{
    /* Return SPI ErrorCode */
    return pHSpi->ErrorCode;
}

/**
  * @}
  */

#endif /* HAL_SPI_I2S_MODULE_ENABLED */

